package com.hanshg.cherry.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.model.*;
import com.hanshg.cherry.base.core.Constants;
import com.hanshg.cherry.base.result.Results;
import com.hanshg.cherry.config.aliyun.AliyunConfig;
import com.hanshg.cherry.config.aliyun.OSSFactory;
import com.hanshg.cherry.dto.OssObjectDto;
import com.hanshg.cherry.service.aliyun.AliYunOssService;
import com.hanshg.cherry.util.file.FileSizeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @author 柠檬水
 */
@Service
@Slf4j
public class AliYunOssServiceImpl implements AliYunOssService {

    @Autowired
    private AliyunConfig aliyunConfig;

    /**
     * 回家上传图像oss
     *
     * @param file 文件
     * @return {@link String}* @throws Exception 异常
     */
    @Override
    public String uploadHomeImageOSS(MultipartFile file) throws Exception {
        if (file.getSize() > 1024 * 1024 * 10) {
            throw new Exception("上传附件大小不能超过10M!");
        }
        String originalFilename = file.getOriginalFilename();
        String substring = originalFilename.substring(originalFilename.lastIndexOf(".")).toLowerCase();
        Random random = new Random();
        String name = random.nextInt(10000) + System.currentTimeMillis() + substring;
        try {
            InputStream inputStream = file.getInputStream();
            this.uploadHomeImageFileOSS(inputStream, name);
            return name;
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("文件上传失败");
        }
    }

    /**
     * 回家图像url
     *
     * @param fileUrl 文件的url
     * @return {@link String}
     */
    @Override
    public String getHomeImageUrl(String fileUrl) {
        if (!StringUtils.isEmpty(fileUrl)) {
            String[] split = fileUrl.split("/");
            return this.getUrl(OSSFactory.build().sysOss.getHomedir()+ split[split.length - 1]);
        }
        return null;
    }

    /**
     * 上传图像文件oss
     *
     * @param inseam   内
     * @param fileName 文件名称
     * @return {@link String}
     */
    @Override
    public String uploadHomeImageFileOSS(InputStream inseam, String fileName) {
        String ret = "";
        try {
            //创建上传Object的Metadata
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentLength(inseam.available());
            objectMetadata.setCacheControl("no-cache");
            objectMetadata.setHeader("Pragma", "no-cache");
            objectMetadata.setContentType(getcontentType(fileName.substring(fileName.lastIndexOf("."))));
            objectMetadata.setContentDisposition("inline;filename=" + fileName);
            //上传文件
            PutObjectResult putResult = OSSFactory.build().ossClient.putObject(OSSFactory.build().sysOss.getBucketName(), OSSFactory.build().sysOss.getHomedir() + fileName, inseam, objectMetadata);
            ret = putResult.getETag();
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        } finally {
            try {
                if (inseam != null) {
                    inseam.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    /**
     * 获取url
     *
     * @param key 关键
     * @return {@link String}
     */
    @Override
    public String getUrl(String key) {
        // 设置URL过期时间为10年  3600l* 1000*24*365*10
        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
        // 生成URL
        URL url = OSSFactory.build().ossClient.generatePresignedUrl(OSSFactory.build().sysOss.getBucketName(), key, expiration);
        if (url != null) {
            return url.toString();
        }
        return null;
    }

    /**
     * getcontent类型
     *
     * @param FilenameExtension 文件扩展名
     * @return {@link String}
     */
    @Override
    public String getcontentType(String FilenameExtension) {
        if (FilenameExtension.equalsIgnoreCase(".bmp")) {
            return "image/bmp";
        }
        if (FilenameExtension.equalsIgnoreCase(".gif")) {
            return "image/gif";
        }
        if (FilenameExtension.equalsIgnoreCase(".jpeg") ||
                FilenameExtension.equalsIgnoreCase(".jpg") ||
                FilenameExtension.equalsIgnoreCase(".png")) {
            return "image/jpeg";
        }
        if (FilenameExtension.equalsIgnoreCase(".html") ||
                FilenameExtension.equalsIgnoreCase(".jsp")) {
            return "text/html";
        }
        if (FilenameExtension.equalsIgnoreCase(".txt")) {
            return "text/plain";
        }
        if (FilenameExtension.equalsIgnoreCase(".md")) {
            return "text/x-markdown";
        }
        if (FilenameExtension.equalsIgnoreCase(".xls") ||
                FilenameExtension.equalsIgnoreCase(".xlsx")) {
            return "application/vnd.ms-excel";
        }
        if (FilenameExtension.equalsIgnoreCase(".pdf")) {
            return "application/pdf";
        }
        if (FilenameExtension.equalsIgnoreCase(".vsd")) {
            return "application/vnd.visio";
        }
        if (FilenameExtension.equalsIgnoreCase(".pptx") ||
                FilenameExtension.equalsIgnoreCase(".ppt")) {
            return "application/vnd.ms-powerpoint";
        }
        if (FilenameExtension.equalsIgnoreCase(".docx") ||
                FilenameExtension.equalsIgnoreCase(".doc")) {
            return "application/msword";
        }
        if (FilenameExtension.equalsIgnoreCase(".xml")) {
            return "text/xml";
        }
        if (FilenameExtension.equalsIgnoreCase(".css")) {
            return "application/x-csi";
        }
        if (FilenameExtension.equalsIgnoreCase(".class")) {
            return "application/x-cit";
        }
        if (FilenameExtension.equalsIgnoreCase(".mp4")) {
            return "video/mpeg4";
        }
        return "image/jpg";
    }

    /**
     * 更新国内图像
     *
     * @param file 文件
     * @return {@link JSONObject}* @throws Exception 异常
     */
    @Override
    public JSONObject updateHomeImage(MultipartFile file) throws Exception {
        if (!Constants.IS_FLAG.equals(aliyunConfig.getFlag())) {
            JSONObject res = new JSONObject();
            res.put("msg", "系统已屏蔽文件上传，请在配置文件中开启");
            res.put("code", 1);
            return res;
        }
        if (file == null || file.getSize() <= 0) {
            throw new Exception("上传文件不能为空");
        }
        String fileName = this.uploadHomeImageOSS(file);
        String fileUrl = this.getHomeImageUrl(fileName);
        return toUpload(fileName, fileUrl);
    }

    /**
     * 文件列表
     *
     * @return {@link List<OSSObjectSummary>}
     */
    @Override
    public Results<OssObjectDto> fileList() {
        // 设置最大个数。
        final int maxKeys = 100;
        // 列举文件。
        ObjectListing objectListing = OSSFactory.build().ossClient.listObjects(new ListObjectsRequest(OSSFactory.build().sysOss.getBucketName(), OSSFactory.build().sysOss.getHomedir(), null, null, maxKeys));
        List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
        List<OssObjectDto> object = new ArrayList<>();
        for (OSSObjectSummary oss : sums) {
            OssObjectDto dto = new OssObjectDto();
            dto.setBucketName(oss.getBucketName());
            dto.setKey(oss.getKey());
            dto.setLastModified(oss.getLastModified());
            dto.setSize(FileSizeUtil.formatFileSize(oss.getSize()));
            dto.setStorageClass(oss.getStorageClass());
            object.add(dto);
        }
        return Results.success(0, object);
    }

    /**
     * 删除文件
     *
     * @param fileName 多个对象名称
     * @return {@link JSONObject}
     */
    @Override
    public JSONObject deleteFile(List<String> fileName) {
        JSONObject res = new JSONObject();
        try {
            /**
             * 删除多个文件
             */
            DeleteObjectsRequest objectsRequest = new DeleteObjectsRequest(OSSFactory.build().sysOss.getBucketName()).withKeys(fileName);
            DeleteObjectsResult deleteObjectsResult = OSSFactory.build().ossClient.deleteObjects(objectsRequest);
            List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
            if (deletedObjects != null && deletedObjects.size() > 0) {
                res.put("msg", "删除成功");
                res.put("code", 200);
            }
        } catch (Exception e) {
            e.printStackTrace();
            res.put("msg", "删除失败");
            res.put("code", 0);
        }
        return res;
    }

    /**
     * 导出操作系统文件
     *
     * @param os         操作系统
     * @param objectName 对象名称
     * @throws IOException ioexception
     */
    @Override
    public void exportOssFile(OutputStream os, String objectName) throws IOException {
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = OSSFactory.build().ossClient.getObject(OSSFactory.build().sysOss.getBucketName(), objectName);
        // 读取文件内容。
        BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
        BufferedOutputStream out = new BufferedOutputStream(os);
        try {
            byte[] buffer = new byte[1024];
            int lenght = 0;
            while ((lenght = in.read(buffer)) != -1) {
                out.write(buffer, 0, lenght);
            }
            if (out != null) {
                out.flush();
                out.close();
            }
            if (in != null) {
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传
     * 上传到阿里云0SS服务器
     *
     * @param fileName 文件名称
     * @param fileUrl  文件的url
     * @return {@link JSONObject}
     */
    private JSONObject toUpload(String fileName, String fileUrl) {
        JSONObject res = new JSONObject();
        JSONObject resUrl = new JSONObject();
        try {
            log.info("上传附件成功" + fileName);
            resUrl.put("src", fileUrl);
            resUrl.put("fileName", fileName);
            res.put("msg", "上传成功");
            res.put("code", 0);
            res.put("data", resUrl);
        } catch (Exception e) {
            resUrl.put("src", "");
            res.put("msg", e.getMessage());
            res.put("code", 1);
            res.put("data", resUrl);
            log.error(e.getMessage(), e);
        }
        return res;
    }
}
